package com.rnkrsoft.suyan.config.server.ajax.executor;


import com.google.gson.JsonSyntaxException;
import com.rnkrsoft.logtrace4j.ErrorContextFactory;
import com.rnkrsoft.suyan.config.server.ajax.config.AjaxConfig;
import com.rnkrsoft.suyan.config.server.ajax.spring.SpringHelper;
import lombok.extern.slf4j.Slf4j;

import javax.doc.DocScanner;
import javax.doc.InterfaceInfo;
import javax.doc.data.IRequest;
import javax.doc.data.IResponse;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * 用于执行Spring中的接口
 */
@Slf4j
class SpringAjaxExecutor extends AbstractAjaxExecutor implements AjaxExecutor{
    final static Map<String, Method> METHODS_CACHE = new HashMap();

    public SpringAjaxExecutor(AjaxConfig ajaxConfig) {
        super(ajaxConfig);
    }

    @Override
    protected IResponse run(InterfaceInfo interfaceInfo, IRequest request) throws Exception{
        ErrorContextFactory.instance().reset();
        Method interfaceMethod = METHODS_CACHE.get(interfaceInfo.getFullMethodName());
        Class serviceClass = null;
        if (interfaceMethod == null) {
            synchronized (this) {
                try {
                    serviceClass = Class.forName(interfaceInfo.getServiceInfo().getServiceClassName());
                    for (Method method : serviceClass.getMethods()) {
                        if (method.getName().equals(interfaceInfo.getMethodName())) {
                            interfaceMethod = method;
                            break;
                        }
                    }
                    if (interfaceMethod == null) {
                        throw new RuntimeException("no such method :" + interfaceInfo.getFullName());
                    }
                } catch (ClassNotFoundException e) {
                    throw new RuntimeException("no such service class :" + interfaceInfo.getServiceInfo().getServiceClassName());
                }
                METHODS_CACHE.put(interfaceInfo.getFullMethodName(), interfaceMethod);
            }
        } else {
            serviceClass = interfaceMethod.getDeclaringClass();
        }

        try {
            Object instance = SpringHelper.getBean(serviceClass);
            Object result = interfaceMethod.invoke(instance, request);
            return (IResponse) result;
        } catch (IllegalAccessException e) {
            log.error("execute service happens error!", e);
            throw e;
        } catch (InvocationTargetException e1) {
            Throwable e = e1.getTargetException();
            log.error("execute service happens error!", e);
            throw new Exception(e);
        }
    }

    @Override
    public ExecutorType getType() {
        return ExecutorType.SPRING;
    }
}
